package com.gitee.wsl.struct.grammar.util

import com.gitee.wsl.struct.grammar.Grammar
import com.gitee.wsl.struct.grammar.parser.Parser
import com.gitee.wsl.struct.grammar.parser.ParserReference
import com.gitee.wsl.struct.grammar.parser.combinator.AbstractChoiceParser
import com.gitee.wsl.struct.grammar.parser.token.LiteralToken
import com.gitee.wsl.struct.grammar.parser.token.RegexToken
import com.gitee.wsl.struct.grammar.parser.token.Token


//fun Grammar<*>.grammar2ebnf() {
//    val gramProps = ArrayList<Any>()
//    val gramPropsNames = ArrayList<String>()
//    fun findName(o : Parser<*>): String? {
//        for (idx in gramProps.indices) {
//            if(gramProps[idx] == o) {
//                return gramPropsNames[idx]
//            }
//        }
//        return null
//    }
//
//    //first collect names/properties from the grammar
//    for (prop in this::class.memberProperties) {
//        prop.isAccessible = true
//        val prop_value = try {
//            prop.getter.call(this)
//        } catch (e: IllegalArgumentException) {
//            prop.getter.call()
//        }
//        when (prop_value) {
//            //order is important
//            is Token -> {
//                gramProps.add(prop_value)
//                gramPropsNames.add(prop.name)
//                //println("terminal : ${prop.name} : ${prop_value} : ${prop_value.javaClass.kotlin}")
//            }
//            is Parser<*> -> {
//                gramProps.add(prop_value)
//                gramPropsNames.add(prop.name)
//                //println("nonterminal : ${prop.name} : ${prop_value}")
//            }
//            //else -> println("?? : ${prop.name} : ${prop_value}")
//        }
//    }
//
//    //now dumpt the EBNF
//    fun obj2rhs(obj : Parser<*>, isFirst : Boolean = false) {
//        when (obj) {
////            is MapCombinator<*,*> -> {
////                val oname = findName(obj.innerParser)
////                if(oname != null) print(" ${oname}")
////                else obj2rhs(obj.innerParser)
////            }
//            is AbstractChoiceParser<*> -> {
//                var sep = ""
//                if(!isFirst) print(" (")
//                for(p in obj.parsers) {
//                    val oname = findName(p)
//                    print(sep)
//                    if(oname != null) print(" $oname")
//                    else obj2rhs(p)
//                    if (sep == "") sep = " |"
//                }
//                if(!isFirst) print(" )")
//            }
////            is AndCombinator<*> -> {
////                val obj_consummers = obj.consumers
////                for (index in 0 until obj_consummers.size) {
////                    val p = obj_consummers[index]
////                    when (p) {
////                        is Parser<*> -> {
////                            val oname = findName(p)
////                            if(oname != null) print(" ${oname}")
////                            else obj2rhs(p)
////                        }
////                        is SkipParser -> {
////                            obj2rhs(p.innerParser)
////                        }
////                        else -> throw IllegalArgumentException()
////                    }
////                }
////            }
////            is OptionalCombinator<*> -> {
////                val oname = findName(obj.parser)
////                if(oname != null) print(" ${oname}?")
////                else {
////                    print(" (")
////                    obj2rhs(obj.parser)
////                    print(" )?")
////                }
////            }
////            is RepeatCombinator<*> -> {
////                val oname = findName(obj.parser)
////                if(oname != null) print(" ${oname}")
////                else {
////                    obj2rhs(obj.parser)
////                }
////                if (obj.atLeast == 0) print("*")
////                else print("+")
////            }
//            //is SkipParser<*> -> {obj2rhs(obj.innerParser)}
////            is SeparatedCombinator<*,*> -> {
////                val tpname = findName(obj.termParser)
////                if (tpname != null) print(" ${tpname}");
////                else obj2rhs(obj.termParser)
////                print(" (")
////                val sepname = findName(obj.separatorParser)
////                if(sepname != null) print(" ${sepname}");
////                else obj2rhs(obj.separatorParser)
////                if (tpname != null) print(" ${tpname}");
////                else obj2rhs(obj.termParser)
////                if (obj.acceptZero) print(" )*")
////                else print(" )+")
////            }
//            is ParserReference<*> -> {
//                val oname = findName(obj.parser)
//                if(oname != null) print(" $oname")
//                else obj2rhs(obj.parser)
//            }
//            //is Separated<*,*> -> {}
//            else -> {
//                val oname = findName(obj)
//                if(oname != null) print(" $oname")
//                else {
//                    val obj_class = obj.javaClass.kotlin
//                    //println("--Token? ${obj_class}")
//                    when (obj) {
//                        is LiteralToken -> {
//                            //println("${name} ::= '${obj.text}'")
//                            print(" '${obj.string}'")
//                        }
////                        is CharToken -> {
////                            //println("${name} ::= '${obj.text}'")
////                            print(" '${obj.text}'")
////                        }
//                        is RegexToken -> {
//                            //println("${name} ::= '??'")
//                            print(" '??'")
//                        }
//                        else -> {print(" (? $obj ?)")}
//                    }
//                }
//            }
//        }
//    }
//    for (idx in gramPropsNames.indices) {
//        val obj = gramProps[idx]
//        val name = gramPropsNames[idx]
//        //println(obj)
//        print("${name} ::=")
//        when (obj) {
////            is MapCombinator<*,*> -> {
////                obj2rhs(obj.innerParser, true)
////            }
//            is AbstractChoiceParser<*> -> {
//                obj2rhs(obj, true)
//            }
////            is AndCombinator<*> -> {
////                obj2rhs(obj, true)
////            }
//            is ParserReference<*> -> {
//                obj2rhs(obj, true)
//            }
//            else -> {
//                val obj_class = obj.javaClass.kotlin
//                //println("--Token? ${obj_class}")
//                when (obj) {
//                    is LiteralToken -> {
//                        //println("${name} ::= '${obj.text}'")
//                        print(" '${obj.string}'")
//                    }
////                    is CharToken -> {
////                        //println("${name} ::= '${obj.text}'")
////                        print(" '${obj.text}'")
////                    }
//                    is RegexToken -> {
//                        //println("${name} ::= '??'")
//                        print(" '??'")
//                    }
//                    else -> {print(" (? $obj ?)")}
//                }
//            }
//        }
//        println("")
//    }
//}
